package com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.OrgUserStuUtil;
import com.xyht.sca_s.student_manage_system.modules.org.entity.SmsOrgStructure;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgStructureMapper;
import com.xyht.sca_s.student_manage_system.modules.student.entity.SmsStudentInfo;
import com.xyht.sca_s.student_manage_system.modules.student.mapper.SmsStudentInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.ChargePlanConstant;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsChargeCategoryDetail;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsChargeOrgItem;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsChargePlan;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsChargePlanStudentStatus;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.req.SmsWnsChargePlanReq;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.req.SmsWnsIdListReq;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.resp.SmsWnsChargePlanResp;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsChargeCategoryDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsChargeOrgItemMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsChargePlanMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsChargePlanStudentStatusMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.service.SmsWnsChargePlanService;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.util.CategoryItemUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isLegalDateRange;
import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;

/**
 * <p>
 * 收费计划表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-01-15
 */
@Service
public class SmsWnsChargePlanServiceImpl extends ServiceImpl<SmsWnsChargePlanMapper, SmsWnsChargePlan> implements SmsWnsChargePlanService {
    @Resource
    private SmsOrgStructureMapper smsOrgStructureMapper;
    @Resource
    private SmsUserMapper smsUserMapper;
    @Resource
    private SmsStudentInfoMapper smsStudentInfoMapper;
    @Resource
    private SmsWnsChargeCategoryDetailMapper smsWnsChargeCategoryDetailMapper;
    @Resource
    private SmsWnsChargeOrgItemMapper smsWnsChargeOrgItemMapper;
    @Resource
    private CategoryItemUtil categoryItemUtil;
    @Resource
    private SmsWnsChargePlanStudentStatusMapper smsWnsChargePlanStudentStatusMapper;
    @Resource
    private OrgUserStuUtil orgUserStuUtil;

    @Override
    @Transactional
    public ResponseResult addPlan(SmsWnsChargePlanReq planReq) {
        if (isNullOrEmpty(planReq.getType())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (isNullOrEmpty(planReq.getName(), planReq.getRangeType(), planReq.getIdList())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if (planReq.getRangeType() == ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_MAJOR) {
            if (isNullOrEmpty(planReq.getGrade())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
        }

        // 校验计划类型
        if (planReq.getType() == ChargePlanConstant.CHARGE_PLAN_TYPE_NEW_STUDENT) {
            // 缴费范围必须为专业
            if (planReq.getRangeType() != ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_MAJOR) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
        } else if (planReq.getType() == ChargePlanConstant.CHARGE_PLAN_TYPE_COMMON) {
            if (isNullOrEmpty(planReq.getStartTime(), planReq.getEndTime())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }

            // 校验开始时间是否晚于结束时间
            if (planReq.getStartTime().after(planReq.getEndTime())) {
                return CommonResult.failed(CommonCodeEnum.WNS_TIME_ILLEGAL);
            }

            // 校验范围粒度
            if (!ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_LIST.contains(planReq.getRangeType())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
        } else {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 校验组织
        List<SmsOrgStructure> orgStructureList;
        String orgLevel = "";
        if (planReq.getRangeType() != ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_USER) {
            orgStructureList = smsOrgStructureMapper.selectBatchIds(planReq.getIdList());
            if (orgStructureList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.ORGANIZATION_NOT_EXIST);
            }

            List<String> orgLevelList = orgStructureList.stream().map(SmsOrgStructure::getLevel).distinct().collect(Collectors.toList());
            if (orgLevelList.size() != 1) {
                return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_PLAN_RANGE_TYPE_NOT_SAME);
            }
            orgLevel = orgLevelList.get(0);
        }

        // 校验范围粒度id集合
        switch (planReq.getRangeType()) {
            case ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_MAJOR:
                if (!orgLevel.equals("4")) {
                    return CommonResult.failed(CommonCodeEnum.ORGANIZATION_NOT_EXIST);
                }

                break;
            case ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_CLASS:
                if (!orgLevel.equals("6")) {
                    return CommonResult.failed(CommonCodeEnum.ORGANIZATION_NOT_EXIST);
                }
                break;
            case ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_USER:
                List<SmsStudentInfo> studentInfoListList = smsStudentInfoMapper.selectBatchIds(planReq.getIdList());
                if (studentInfoListList.isEmpty()) {
                    return CommonResult.failed(CommonCodeEnum.STUDENT_NOT_EXIST);
                }
                break;
        }

        // 添加计划
        SmsWnsChargePlan plan = new SmsWnsChargePlan();
        BeanUtils.copyProperties(planReq, plan, "id");
        plan.setIdList(JSON.toJSONString(planReq.getIdList()));
        plan.setIsInitialized(false); // 还未初始化
        plan.setIsPublish(false); // 还未发布
        this.save(plan);

        return CommonResult.success(plan.getId());
    }

    @Override
    @Transactional
    public ResponseResult updatePlan(SmsWnsChargePlanReq planReq) {
        if (isNullOrEmpty(planReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsChargePlan plan = this.getById(planReq.getId());
        if (plan == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_PLAN_NOT_EXIST);
        }

        if (!isNullOrEmpty(planReq.getStartTime(), planReq.getEndTime())) {
            if (!isLegalDateRange(planReq.getStartTime(), planReq.getEndTime())) {
                return CommonResult.failed(CommonCodeEnum.WNS_TIME_ILLEGAL);
            }
        }

        BeanUtils.copyProperties(planReq, plan);
        // 设置收费类别详情id集合
        if (planReq.getDetailIdList() != null && !planReq.getDetailIdList().isEmpty()) {
            List<SmsWnsChargeCategoryDetail> detailList = smsWnsChargeCategoryDetailMapper.selectBatchIds(planReq.getDetailIdList());
            if (detailList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_CATEGORY_DETAIL_NOT_EXIST);
            }
            List<String> detailIdList = detailList.stream().map(SmsWnsChargeCategoryDetail::getId).collect(Collectors.toList());
            plan.setDetailIdList(JSON.toJSONString(detailIdList));
        }

        // 修改计划
        if (!isNullOrEmpty(planReq.getRangeType())) {
            if (!Objects.equals(planReq.getRangeType(), plan.getRangeType())) {
                // 校验组织
                List<SmsOrgStructure> orgStructureList = new ArrayList<>();
                if (planReq.getRangeType() != ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_USER) {
                    orgStructureList = smsOrgStructureMapper.selectBatchIds(planReq.getIdList());
                    if (orgStructureList.isEmpty()) {
                        return CommonResult.failed(CommonCodeEnum.ORGANIZATION_NOT_EXIST);
                    }
                }
                List<String> orgLevelList = orgStructureList.stream().map(SmsOrgStructure::getLevel).distinct().collect(Collectors.toList());
                if (orgLevelList.size() != 1) {
                    return CommonResult.failed(CommonCodeEnum.WNS_TIME_ILLEGAL);
                }
                String orgLevel = orgLevelList.get(0);

                // 校验范围粒度id集合
                switch (planReq.getRangeType()) {
                    case ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_MAJOR:
                        if (!orgLevel.equals("4")) {
                            return CommonResult.failed(CommonCodeEnum.ORGANIZATION_NOT_EXIST);
                        }
                        break;
                    case ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_CLASS:
                        if (!orgLevel.equals("6")) {
                            return CommonResult.failed(CommonCodeEnum.ORGANIZATION_NOT_EXIST);
                        }
                        break;
                    case ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_USER:
                        List<SmsStudentInfo> studentInfoListList = smsStudentInfoMapper.selectBatchIds(planReq.getIdList());
                        if (studentInfoListList.isEmpty()) {
                            return CommonResult.failed(CommonCodeEnum.STUDENT_NOT_EXIST);
                        }
                        break;
                }

                // 设置范围id集合
                plan.setIdList(JSON.toJSONString(planReq.getIdList()));
            }
        }

        this.updateById(plan);

        return CommonResult.success();
    }

    @Override
    public ResponseResult listPlan(Integer pageNum, Integer pageSize, Integer type, String searchStr) {
        LambdaQueryWrapper<SmsWnsChargePlan> queryWrapper = new LambdaQueryWrapper<SmsWnsChargePlan>()
                .eq(SmsWnsChargePlan::getType, type)
                .orderByDesc(SmsWnsChargePlan::getCreateTime);

        if (!isNullOrEmpty(searchStr)) {
            StringUtils.deleteWhitespace(searchStr);
            queryWrapper.and(i -> i.like(SmsWnsChargePlan::getName, searchStr).or()
                    .like(SmsWnsChargePlan::getDescription, searchStr));
        }

        Page<SmsWnsChargePlan> page = new Page<>(pageNum, pageSize);
        this.page(page, queryWrapper);

        List<SmsWnsChargePlanResp> collect = page.getRecords().stream().map(plan -> {
            SmsWnsChargePlanResp planResp = new SmsWnsChargePlanResp();
            BeanUtils.copyProperties(plan, planResp);
            planResp.setIdList(JSON.parseArray(plan.getIdList(), String.class));

            // 设置收费范围
            if (plan.getRangeType() != ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_USER) {
                List<SmsOrgStructure> orgStructureList = smsOrgStructureMapper.selectBatchIds(planResp.getIdList());
                planResp.setOrgList(orgStructureList);
            } else {
                List<SmsStudentInfo> studentInfoList = smsStudentInfoMapper.selectBatchIds(planResp.getIdList());
                planResp.setStuInfoList(studentInfoList);
            }

            // 设置收费类别详情集合
            if (!isNullOrEmpty(plan.getDetailIdList())) {
                List<SmsWnsChargeCategoryDetail> detailList = smsWnsChargeCategoryDetailMapper.selectBatchIds(JSON.parseArray(plan.getDetailIdList(), String.class));
                if (!detailList.isEmpty()) {
                    planResp.setDetailList(detailList);
                }
            }

            return planResp;
        }).collect(Collectors.toList());

        return CommonResult.success(collect, (int) page.getTotal());
    }

    @Override
    public ResponseResult planDetail(String id) {
        SmsWnsChargePlan plan = this.getById(id);
        if (plan == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_PLAN_NOT_EXIST);
        }

        SmsWnsChargePlanResp planResp = new SmsWnsChargePlanResp();
        BeanUtils.copyProperties(plan, planResp);
        planResp.setIdList(JSON.parseArray(plan.getIdList(), String.class));

        // 设置收费范围
        if (plan.getRangeType() != ChargePlanConstant.CHARGE_PLAN_RANGE_TYPE_USER) {
            List<SmsOrgStructure> orgStructureList = smsOrgStructureMapper.selectBatchIds(planResp.getIdList());
            planResp.setOrgList(orgStructureList);
        } else {
            List<SmsStudentInfo> studentInfoList = smsStudentInfoMapper.selectBatchIds(planResp.getIdList());
            planResp.setStuInfoList(studentInfoList);
        }

        // 设置收费类别详情集合
        if (!isNullOrEmpty(plan.getDetailIdList())) {
            List<SmsWnsChargeCategoryDetail> detailList = smsWnsChargeCategoryDetailMapper.selectBatchIds(JSON.parseArray(plan.getDetailIdList(), String.class));
            if (!detailList.isEmpty()) {
                planResp.setDetailList(detailList);
            }
        }

        return CommonResult.success(planResp);
    }

    @Override
    public ResponseResult getStuIdByStuIdCard(SmsWnsIdListReq idListReq) {
        List<String> idList = idListReq.getIdList();
        if (idList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 身份证号或手机号或学号匹配
        List<SmsStudentInfo> studentInfoList = smsStudentInfoMapper.selectList(new LambdaQueryWrapper<SmsStudentInfo>()
                .in(SmsStudentInfo::getStuIdCard, idList)
                .or()
                .in(SmsStudentInfo::getStuTel, idList)
                .or()
                .in(SmsStudentInfo::getStuNo, idList));
        if (studentInfoList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.STUDENT_NOT_EXIST);
        }

        List<String> stuIdList = studentInfoList.stream().map(SmsStudentInfo::getId).collect(Collectors.toList());

        return CommonResult.success(stuIdList, stuIdList.size());
    }

    @Override
    public ResponseResult publishPlan(SmsWnsChargePlanReq planReq) {
        if (isNullOrEmpty(planReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsChargePlan plan = this.getById(planReq.getId());
        if (plan == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_PLAN_NOT_EXIST);
        }

        plan.setIsPublish(true); // 设置为已发布
        this.updateById(plan);

        // 未初始化先进行初始化
        if (!plan.getIsInitialized()) {
            boolean initSuccess = categoryItemUtil.initializeCategoryItemByPlanId(plan.getId());
            if (!initSuccess) {
                return CommonResult.failed(CommonCodeEnum.FAIL);
            }
        }

        return CommonResult.success();
    }

    @Override
    public ResponseResult getAllGrades() {
        List<SmsOrgStructure> orgStructureList = smsOrgStructureMapper.getAllGrades();

        // 对年级进行去重排序
        List<String> grades = orgStructureList.stream().map(SmsOrgStructure::getOrgName).distinct()
                .sorted().collect(Collectors.toList());

        return CommonResult.success(grades, grades.size());
    }

    @Override
    @Transactional
    public ResponseResult delPlan(SmsWnsIdListReq idListReq) {
        if (idListReq.getIdList().isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 删除收费项
        smsWnsChargeOrgItemMapper.delete(new LambdaQueryWrapper<SmsWnsChargeOrgItem>()
                .in(SmsWnsChargeOrgItem::getPlanId, idListReq.getIdList()));

        // 删除学生收费情况
        smsWnsChargePlanStudentStatusMapper.delete(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                .in(SmsWnsChargePlanStudentStatus::getPlanId, idListReq.getIdList()));

        // 删除收费计划
        this.removeByIds(idListReq.getIdList());

        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult pausePlan(SmsWnsChargePlanReq planReq) {
        if (isNullOrEmpty(planReq.getId(), planReq.getIsPause())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsChargePlan plan = this.getById(planReq.getId());
        if (plan == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_PLAN_NOT_EXIST);
        }

        plan.setIsPause(planReq.getIsPause()); // 暂停/启用计划
        this.updateById(plan);

        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult addStudent(SmsWnsChargePlanReq planReq) {
        if (isNullOrEmpty(planReq.getId(), planReq.getUserId(), planReq.getOrgId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 校验该计划是否已包含该用户
        Integer count = smsWnsChargePlanStudentStatusMapper.selectCount(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                .eq(SmsWnsChargePlanStudentStatus::getPlanId, planReq.getId())
                .eq(SmsWnsChargePlanStudentStatus::getUserId, planReq.getUserId()));
        if (count > 0) {
            return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_PLAN_STUDENT_EXIST);
        }

        // 校验计划是否存在
        SmsWnsChargePlan plan = this.getById(planReq.getId());
        if (plan == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_PLAN_NOT_EXIST);
        }

        // 校验计划是否未暂停
        if (!plan.getIsPause()) {
            return CommonResult.failed(CommonCodeEnum.WNS_CHARGE_PLAN_NOT_PAUSE);
        }

        if (!categoryItemUtil.addCategoryItem(planReq.getId(), planReq.getOrgId(), planReq.getUserId())) {
            CommonResult.failed(CommonCodeEnum.FAIL);
        }

        return CommonResult.success();
    }

    @Override
    public ResponseResult getStuIdListByUserIdList(SmsWnsIdListReq idListReq) {
        if (idListReq.getIdList().isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        List<String> stuIdList = categoryItemUtil.getStuIdListByUserIdList(idListReq.getIdList());

        return CommonResult.success(stuIdList);
    }

    @Override
    public ResponseResult getUserIdListByStuIdList(SmsWnsIdListReq idListReq) {
        if (idListReq.getIdList().isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        List<String> userIdList = orgUserStuUtil.getUserIdListByStuIdList(idListReq.getIdList());

        return CommonResult.success(userIdList);
    }
}
